import WebSocket, { WebSocketServer } from 'ws'

import http from 'http'
import fs from 'fs'
import path from 'path'

import { reducer } from './reducer'
import { thunk, ThunkMiddleware } from 'redux-thunk'
import { createStore, applyMiddleware } from 'redux'

import {
  newPlayerConnection,
  newMatch,
  connectMatch,
  hungUp,
  move,
  renewLastSeen,
} from './actions'
import { MatchId, State, ActionTypes } from './types'

import { MESSAGE_TYPE, PlayerId, parseMessage } from '@kenrick95/c4'

const port = parseInt(process.env.PORT || '') || 8080

// 创建 HTTP 服务器（用于同时支持 WebSocket 和静态文件）
const server = http.createServer(handleRequest)
const wss = new WebSocketServer({ server })
// const wss = new WebSocketServer({host: '0.0.0.0',  port: port })
console.log(`[服务器] 已开始监听 ws://0.0.0.0:${port}`)

function configureStore() {
  const middleware = applyMiddleware(
    thunk as ThunkMiddleware<State, ActionTypes>,
  )
  return createStore(reducer, middleware)
}
export const store = configureStore()

function alivenessLoop() {
  const state = store.getState()
  const now = Date.now()
  for (const player of Object.values(state.players)) {
    if (now - player.lastSeen >= 60000) {
      player.ws.terminate()
    }

    player.ws.ping()
  }
}

wss.on('connection', (ws: WebSocket) => {
  let playerId: null | PlayerId = null
  let matchId: null | MatchId = null

  ws.on('pong', () => {
    if (!playerId) {
      return
    }
    store.dispatch(renewLastSeen(playerId))
  })

  ws.on('message', (message: string) => {
    const parsedMessage = parseMessage(message)
    switch (parsedMessage.type) {
      case MESSAGE_TYPE.NEW_PLAYER_CONNECTION_REQUEST: {
        playerId = store.dispatch(
          newPlayerConnection(ws, parsedMessage.payload.playerName),
        )
        break
      }
      case MESSAGE_TYPE.NEW_MATCH_REQUEST:
        {
          if (!playerId) {
            return
          }
          matchId = store.dispatch(newMatch(playerId))
        }
        break
      case MESSAGE_TYPE.CONNECT_MATCH_REQUEST:
        {
          if (!playerId) {
            return
          }
          matchId = store.dispatch(
            connectMatch(playerId, parsedMessage.payload.matchId),
          )
        }
        break
      case MESSAGE_TYPE.MOVE_MAIN:
        {
          if (!playerId) {
            return
          }
          store.dispatch(move(playerId, matchId, parsedMessage.payload.column))
        }
        break
      case MESSAGE_TYPE.HUNG_UP:
        {
          if (!playerId) {
            return
          }
          store.dispatch(hungUp(playerId))
        }
        break
    }
  })
  ws.on('close', () => {
    if (!playerId) {
      return
    }
    store.dispatch(hungUp(playerId))
  })
})
setInterval(alivenessLoop, 30000)

// ================= 新增：原生 http 提供静态文件服务 ================
const DIST_DIR = path.join(__dirname, '../../dist') // 根据实际情况调整路径

function handleRequest(req: http.IncomingMessage, res: http.ServerResponse) {
  // 防止路径穿越攻击
  const url = req.url ?? '/index.html'
  let filePath = path.join(DIST_DIR, url === '/' ? 'index.html' : url)
  filePath = path.normalize(filePath)
  if (!filePath.startsWith(DIST_DIR)) {
    res.writeHead(403)
    res.end('Forbidden')
    return
  }

  fs.stat(filePath, (err, stats) => {
    if (err || !stats.isFile()) {
      // 文件不存在，返回 index.html（SPA 支持）
      fs.readFile(path.join(DIST_DIR, 'index.html'), (err, data) => {
        if (err) {
          res.writeHead(500)
          res.end('Internal Server Error')
        } else {
          res.writeHead(200, { 'Content-Type': 'text/html' })
          res.end(data)
        }
      })
    } else {
      // 读取并发送文件
      fs.readFile(filePath, (err, data) => {
        if (err) {
          res.writeHead(500)
          res.end('Internal Server Error')
        } else {
          const extname = path.extname(filePath)
          const contentType: Record<string, string> = {
            '.html': 'text/html',
            '.js': 'application/javascript',
            '.css': 'text/css',
            '.json': 'application/json',
            '.png': 'image/png',
            '.jpg': 'image/jpeg',
            '.gif': 'image/gif',
            '.wav': 'audio/wav',
            '.mp4': 'video/mp4',
            '.woff': 'application/font-woff',
            '.ttf': 'application/font-ttf',
            '.eot': 'application/vnd.ms-fontobject',
            '.svg': 'application/image/svg+xml',
          }

          res.writeHead(200, { 'Content-Type': contentType[extname] || 'application/octet-stream' })
          res.end(data)
        }
      })
    }
  })
}
// ============================================================

// 启动服务
server.listen(port, '0.0.0.0', () => {
  console.log(`[服务器] 已开始监听 ws://0.0.0.0:${port}`)
  console.log(`[前端] 已开始监听 http://0.0.0.0:${port}`)
})

if (import.meta.hot) {
  import.meta.hot.on('vite:beforeFullReload', () => {
    console.log('重新加载前关闭服务器')
    wss.close()
  })
}
